﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
using HtmlAgilityPack;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
using VH.SharePoint.Api.Entensions;
using WebPart = Microsoft.SharePoint.WebPartPages.WebPart;

namespace VH.SharePoint.Api.Helpers
{
    public static class PageHelper
    {
        public static string GetHtmlUrlAbsoluteContent(string html, SPSite site)
        {
            if (string.IsNullOrEmpty(html)) return string.Empty;
            HtmlDocument htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(html);
            var aNodes = (from d in htmlDoc.DocumentNode.Descendants()
                                where d.Name.Equals("a",StringComparison.InvariantCultureIgnoreCase) &&
                                d.Attributes.Contains("href") && d.Attributes["href"].Value.StartsWith("/")
                                select d);
            foreach (var aNode in aNodes)
            {
                var href = aNode.Attributes["href"];
                var absUrl = site.MakeFullUrl(href.Value);
                href.Value = absUrl;
            }
            var imgNodes = (from d in htmlDoc.DocumentNode.Descendants()
                          where d.Name.Equals("img", StringComparison.InvariantCultureIgnoreCase) &&
                          d.Attributes.Contains("src") && d.Attributes["src"].Value.StartsWith("/")
                          select d);
            foreach (var imgNode in imgNodes)
            {
                var src = imgNode.Attributes["src"];
                var absUrl = site.MakeFullUrl(src.Value);
                src.Value = absUrl;
            }

            return htmlDoc.DocumentNode.InnerHtml;
        }

        private static Dictionary<string, string> StylesMap { get; set; }

        static PageHelper()
        {
            StylesMap = new Dictionary<string, string>
                {
                    {"H1","ms-rteElement-H1"},
                    {"H2","ms-rteElement-H2"},
                    {"H3","ms-rteElement-H3"},
                    {"H4","ms-rteElement-H4"},
                    {"HR","ms-rteElement-Hr"},
                    {"P","ms-rteElement-P"},
                    {"SPAN","ms-rteStyle-Normal"},
                };

        }

        public static string SetDefaultMarkupStyles(string html)
        {
            if (string.IsNullOrEmpty(html)) return string.Empty;
            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(html);

            var nodes = (from d in htmlDoc.DocumentNode.Descendants()
                         where StylesMap.ContainsKey(d.Name.ToUpperInvariant()) && !d.Attributes.Contains("class")
                          select d);
            foreach (var node in nodes)
            {
                node.Attributes.Add("class", StylesMap[node.Name.ToUpperInvariant()]);
            }
            return htmlDoc.DocumentNode.InnerHtml;
        }

        public static string WrapSrciptTagIntCewp(SPFile file, string html)
        {
            if (file == null) return string.IsNullOrEmpty(html)?string.Empty:html;
            if (string.IsNullOrEmpty(html)) return string.Empty;

            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(html);

            using (var wpmgr = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
            {
                //Remove existing embeded wp's
                ClearEmbededWps(wpmgr);

                var nodes = (from n in htmlDoc.DocumentNode.Descendants()
                                where ScriptTags.Any(t => n.Name.Equals(t, StringComparison.InvariantCultureIgnoreCase))
                                select n).ToList();

                for (var i = nodes.Count - 1; i >= 0; i--)
                {
                    var node = nodes[i];
                    if (node.Name.Equals("embed") && node.ParentNode.Name.Equals("object"))
                    {
                        continue;
                    }
                    //if (node.Name.Equals("object"))
                    //    node = node.ParentNode;
                    var parentNode = node.ParentNode;
                    var storageKey = CreateEmbededCewp(wpmgr, node.OuterHtml);
                    var newChild = HtmlNode.CreateNode(string.Format(EmbedWPMarker, storageKey));
                    parentNode.ReplaceChild(newChild, node);
                    if (parentNode.Attributes.Contains("class") &&
                        parentNode.Attributes["class"].Value.ToLower().Contains("wlwritereditablesmartcontent"))
                    {
                        var legendChild = parentNode.Descendants("div").LastOrDefault();
                        if (legendChild != null && legendChild.Attributes.Contains("style"))
                        {
                            var styleAttr = legendChild.Attributes["style"];
                            styleAttr.Value = ClearRegex.Replace(styleAttr.Value, string.Empty);
                        }
                    }
                }
                    
            }
            
            return htmlDoc.DocumentNode.InnerHtml;
            
            
            
        }

        private static readonly Regex ClearRegex = new Regex("((?:clear:[^;]*?)(?:;|'))");
        private static readonly string EmbedZoneId = "wpz";
        private static readonly string[] ScriptTags = new[] { "object", "embed" };
        private static readonly string EmbedWPMarker = "<div class=\"ms-rtestate-read ms-rte-wpbox\" contentEditable=\"false\"><div class=\"ms-rtestate-read {0}\" id=\"div_{0}\"></div><div style='display:none' id=\"vid_{0}\"></div></div>";

        private static void ClearEmbededWps(SPLimitedWebPartManager wpmgr)
        {
            for (var i = wpmgr.WebParts.Count - 1; i >= 0; i--)
            {
                var wp = wpmgr.WebParts[i] as WebPart;
                if (wp == null || !wp.ZoneID.Equals(EmbedZoneId, StringComparison.InvariantCultureIgnoreCase)) continue;
                wpmgr.DeleteWebPart(wp);
            }
        }

        private static Guid CreateEmbededCewp(SPLimitedWebPartManager wpmgr, string html)
        {
            var wp = new ContentEditorWebPart();
            wp.SetContent(html);
            //wp.Content = doc.DocumentElement;
            wp.Title = "Scripts";
            wp.ChromeType = PartChromeType.None;
            wp.AllowEdit = false;
            wp.AllowZoneChange = false;
            wp.AllowHide = false;
            wp.AllowClose = false;
            wp.AllowMinimize = false;
            wp.AllowConnect = false;
            wp.BorderColor = System.Drawing.Color.Transparent;
            wp.BackColor = System.Drawing.Color.Transparent;
            wp.BorderWidth = 0;
            wp.BorderStyle = BorderStyle.None;
            wp.ExportMode = WebPartExportMode.None;
            wp.SuppressWebPartChrome = true;
            wpmgr.AddWebPart(wp, EmbedZoneId, 0);
            wpmgr.SaveChanges(wp);
            return wpmgr.GetStorageKey(wp);
        }

        private static string GetCewpContent(Guid storageKey, SPLimitedWebPartManager wpmgr)
        {
            try
            {
                var wp = wpmgr.WebParts[storageKey] as ContentEditorWebPart;
                return wp == null ? string.Empty : wp.GetContent();
            }
            catch (Exception ex)
            {
                //WP Not Found
                return string.Empty;
            }
        }


        public static string GetEditableContent(SPFile file, string html)
        {
            if (file == null) return string.IsNullOrEmpty(html) ? string.Empty : html;
            if (string.IsNullOrEmpty(html)) return string.Empty;
            var htmlDoc = new HtmlDocument();
            htmlDoc.LoadHtml(html);

            using (var wpmgr = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
            {
                var nodes = (from n in htmlDoc.DocumentNode.Descendants()
                             where n.Attributes.Contains("class") && n.Attributes["class"].Value.Contains("ms-rte-wpbox")
                             select n.Descendants("div").FirstOrDefault(d => d.Id.StartsWith("div_"))).ToList();

                for (var i = nodes.Count - 1; i >= 0; i--)
                {
                    var node = nodes[i];
                    var replaceNode = node.ParentNode;
                    var storageKey = new Guid(node.Id.Substring(4).Replace('_','-'));
                    var content = GetCewpContent(storageKey, wpmgr);
                    if (string.IsNullOrEmpty(content))
                    {
                        replaceNode.Remove();
                        continue;
                    }
                    var newChild = HtmlNode.CreateNode(content);
                    replaceNode.ParentNode.ReplaceChild(newChild, replaceNode);
                }
            }

            return htmlDoc.DocumentNode.InnerHtml;
        }
    }
}
